#include <sys/socket.h>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>

using namespace std;
int main(){

    int listenfd=socket(AF_INET,SOCK_STREAM,0);
    if(listenfd==-1){
        cout<<"创建失败！"<<endl;
        exit(-1);
    }
    struct sockaddr_in saddr;
    saddr.sin_family=AF_INET;
    saddr.sin_addr.s_addr=INADDR_ANY;
    // inet_pton(AF_INET,"192.168.110.130",&saddr.sin_addr.s_addr);
    //主机字节序转换为网络字节序
    saddr.sin_port=htons(9990);

    //端口复用
    int optval=1;
    setsockopt(listenfd,SOL_SOCKET,SO_REUSEPORT,&optval,sizeof(optval));

    int ret=bind(listenfd,(struct sockaddr*) &saddr,sizeof(saddr));
    if(ret==-1){
        cout<<"bind error"<<endl;
        exit(-1);
    }
    ret= listen(listenfd,8);
    if(ret==-1){
        cout<<"listen error"<<endl;
        exit(-1);
    }
    

    cout<<"server listening on port "<<saddr.sin_port<<"..."<<endl;

    while(true){
        //监听客户端连接
        struct sockaddr_in clientAddrs;
        socklen_t lenClient=sizeof(clientAddrs);
        int cfd=accept(listenfd,(struct sockaddr *) &clientAddrs, &lenClient);

        if(cfd==-1){
            cout<<"accept error"<<endl;
            exit(-1);
        }
        //创建一个子进程
        pid_t pid=fork();
        if(pid==0){
            //子进程
            //输出客户端信息
            char clientIP[16];
            inet_ntop(AF_INET,&clientAddrs.sin_addr.s_addr,clientIP,sizeof(clientIP));
            //网络字节序转换为主机字节序
            unsigned short clientPort=ntohs(clientAddrs.sin_port);
            cout<<"client addr="<<clientIP<<"    client port="<<clientPort<<endl;

            //通信
            char buf[1024];
            while(true){
                int num=recv(cfd,buf,sizeof(buf),0);
                if(num==-1){
                    cout<<"read error"<<endl;
                    exit(-1);
                }else{
                    cout<<"read data="<<buf<<endl;
                }
                const char* response="hello, from server";
                send(cfd,response,strlen(response),0);
            }
            close(cfd); 
        }
    }
    close(listenfd);
    return 0;
}